package org.dromara.system.listener;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.dromara.system.domain.bo.OrderSalesDataBo;
import org.dromara.system.domain.vo.OrderSalesDataImportVo;
import org.dromara.system.domain.vo.OrderSalesDataVo;
import org.dromara.system.service.IOrderSalesDataService;
import org.dromara.system.service.ISalesDataService;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.*;
import org.dromara.common.excel.core.ExcelListener;
import org.dromara.common.excel.core.ExcelResult;
import org.dromara.common.satoken.utils.LoginHelper;

import java.util.List;

/**
 * 订单销售数据导入自定义监听
 */
@Slf4j
public class OrderSalesDataListener extends AnalysisEventListener<OrderSalesDataImportVo> implements ExcelListener<OrderSalesDataImportVo> {

    private final IOrderSalesDataService orderSalesDataService;
    private final ISalesDataService salesDataService;

    private final Long operUserId;

    private int successNum = 0;
    private int failureNum = 0;

    private String formattedDate = null;

    private final StringBuilder successMsg = new StringBuilder();
    private final StringBuilder failureMsg = new StringBuilder();

    public OrderSalesDataListener() {
        this.orderSalesDataService = SpringUtils.getBean(IOrderSalesDataService.class);
        this.salesDataService = SpringUtils.getBean(ISalesDataService.class);
        this.operUserId = LoginHelper.getUserId();
    }

    @Override
    public void invoke(OrderSalesDataImportVo orderSalesDataImportVo, AnalysisContext analysisContext) {
        formattedDate = DateUtils.formatDate(orderSalesDataImportVo.getCreationTime());
        OrderSalesDataVo dataVo = orderSalesDataService.queryOrderByOrderNoAndTime(orderSalesDataImportVo.getSystemOrderNumber(), formattedDate);
        try {
            processOrderSalesData(orderSalesDataImportVo, dataVo, formattedDate);
            successNum++;
        } catch (Exception e) {
            handleImportFailure(e);
        }
    }

    private void processOrderSalesData(OrderSalesDataImportVo orderSalesDataImportVo, OrderSalesDataVo dataVo, String formattedDate) {
        OrderSalesDataBo orderSalesData = BeanUtil.toBean(orderSalesDataImportVo, OrderSalesDataBo.class);
        if (ObjectUtil.isNotNull(orderSalesData)) {
            if (ObjectUtils.isEmpty(dataVo)) {
                insertNewOrderSalesData(orderSalesData);
            } else {
                updateExistingOrderSalesData(orderSalesData, formattedDate);
            }
        }

    }

    private void insertNewOrderSalesData(OrderSalesDataBo orderSalesData) {
        orderSalesData.setCreateBy(operUserId);
        orderSalesDataService.insertByBo(orderSalesData);
    }

    private void updateExistingOrderSalesData(OrderSalesDataBo orderSalesData, String formattedDate) {
        orderSalesDataService.updateOrderByOrderNoAndTime(orderSalesData, formattedDate);
    }

    private void handleImportFailure(Exception e) {
        failureNum++;
        String msg = "<br/>总共 " + failureNum + " 条导入失败：";
        String message = e.getMessage();
        if (e instanceof ConstraintViolationException cvException) {
            message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
        }
        failureMsg.append(msg).append(message);
        log.error(msg, e);
    }

    @Override
    public ExcelResult<OrderSalesDataImportVo> getExcelResult() {
        return new ExcelResult<>() {

            @Override
            public String getAnalysis() {
                if (failureNum > 0) {
                    failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
                    throw new ServiceException(failureMsg.toString());
                } else {
                    salesDataService.asyncInsertSalesData(formattedDate, operUserId);
                    successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条");
                }
                return successMsg.toString();
            }

            @Override
            public List<OrderSalesDataImportVo> getList() {
                return null;
            }

            @Override
            public List<String> getErrorList() {
                return null;
            }
        };
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }
}
